﻿
//系统头文件放上边
#include <stdio.h>
#include <stdlib.h>
#include <regex>
//自定义头文件放下边,因为g++中用了-I参数，所以这里用<>也可以
#include "ngx_func.h"     //函数声明
#include "ngx_c_conf.h"   //和配置文件处理相关的类,名字带c_表示和类有关

//静态成员赋值
CConfig *CConfig::m_instance = NULL;
pthread_once_t CConfig::once = PTHREAD_ONCE_INIT;
//构造函数
CConfig::CConfig()
{		
}

//析构函数
CConfig::~CConfig()
{    
    configs.clear();
}
#include <iostream>
#include <fstream>
#include <sstream>
//去字符串两边的空格
static void trim(std::string &s) 
{
    if (s.empty()) 
    {
        return ;
    }
    s.erase(0,s.find_first_not_of(" "));
    s.erase(s.find_last_not_of(" ") + 1);
}
static bool is_match(const std::string& line, std::string partten)
{
    std::regex re(partten);
    std::smatch match;
    if(std::regex_match(line, match, re))
    {
        return true;
    }
    return false;

}
static bool is_match(const std::string& line, std::string partten, std::vector<std::string>& res)
{
    std::regex re(partten);
    std::smatch match;
    if(std::regex_match(line, match, re))
    {
        auto begin = match.begin() + 1;
        while(begin != match.end())
        {
            res.push_back(*begin);
            begin += 1;
        }
        return true;
    }
    return false;
}
static bool  is_section(const std::string& line, std::string& section)
{
    std::string partten(R"(^\s*\[\s*(\w+)\s*\]\s*$)");
    std::vector<std::string> res;
    if(!is_match(line, partten, res))
    {
        return false;
    }
    section = res[0];
    return true;
}
static bool is_key_value(const std::string& line, std::string& key, std::string& value)
{
    std::string partten(R"(^\s*(\w+)\s*=\s*(.+?)\s*$)");
    std::vector<std::string> res;
    if(!is_match(line, partten, res))
    {
        return false;
    }
    key = res[0];
    value = res[1];
    return true;
}
static bool is_annotation(const std::string& line)
{
    return is_match(line, R"(^\s*#.*$)");
}
//装载配置文件
bool CConfig::Load(const char *pconfName) 
{   
    std::ifstream ifs(pconfName);
    configs.clear();
    if(!ifs.good())
    {
        printf("%s.%d\r\n", __FILE__, __LINE__);
        return false;
    }
    configs["default"] = config_kv_t();
    int line_nums = 0;
    std::string line_str;
    std::string section="default";
    std::string key, value;
    while(!ifs.eof() && ifs.good())
    {
		getline(ifs, line_str);
		line_nums += 1;
		/*
		 * [session]
		 * key = val
		 * # 注释
		 */
		trim(line_str);
        // 空行
		if(line_str.size() == 0)
		{
            continue;
		}
        // 段开始
        if(is_section(line_str, section))
        {
            if(configs.find(section) == configs.end())
            {
                configs[section] =  config_kv_t();
            }
        }
        else if(is_key_value(line_str, key, value))
        {
            configs[section][key] = value;
        }
        else if(is_annotation(line_str))
        {
            continue;
        }
        else
        {
            configs.clear();
            // printf("line = %s\r\n", line_str.c_str());
            std::cout << line_str << std::endl;
            printf("%s.%d\n", __FILE__, __LINE__);
            return false;
        }
    }
    return true;
}

//根据ItemName获取配置信息字符串，不修改不用互斥
const char *CConfig::GetString(const char *p_itemname, const char* sectionname)
{
	if(configs[sectionname].find(p_itemname) == configs[sectionname].end())
    {
        return NULL;
    }
    return configs[sectionname][p_itemname].c_str();
}
//根据ItemName获取数字类型配置信息，不修改不用互斥
int CConfig::GetIntDefault(const char *p_itemname,const int def, const char* sectionname)
{
    const char* res = GetString(p_itemname, sectionname);
    int val = 0;
    if(res == NULL)
    {
        return def;
    }
    else if(sscanf(res, "%d", &val) > 0)
    {
        return val;
    }
	return def;
}



